;;;
;;; source4.lisp: Source code for LISP tutorial 4
;;; Philip W. L. Fong
;;; SFU CMPT 310 (2001-1)
;;;

;;
;; Global Counter Abstraction
;;

(defparameter *counter* 0 
  "Counter to keep track of ....")

(defparameter *threshold* 4
  "Counter will be reset to zero when its value reaches this threshold.")

(defun counter-inc ()
  "Increment global counter by one."
  (if (>= (1+ *counter*) *threshold*)
      (setf *counter* 0)
    (incf *counter*)))

(defun counter-value ()
  "Return current value of global counter."
  *counter*)

(defun counter-threshold ()
  "Return current threshold of global counter."
  *threshold*)

(defun counter-set-threshold (th)
  "Set counter threshold to TH."
  (setf *threshold* th)
  (if (>= *counter* *threshold*)
      (setf *counter* 0))
  *threshold*)

;;
;; Encapsulated Counter Objects
;;

(defun make-counter ()
  "Create a new instance of a counter object."
  (let ((counter 0))
    (list #'(lambda ()
	      (incf counter))
	  #'(lambda ()
	      (setf counter 0)))))

(defun counter-increment (counter)
  "Increment counter."
  (funcall (first counter)))

(defun counter-reset (counter)
  "Reset counter."
  (funcall (second counter)))

;;
;; Iterative Constructs
;;

(defun fibonacci (n)
  "Compute the N'th Fibonacci number."
  (do ((f1 0 f2)
       (f2 1 (+ f1 f2))
       (i  0 (1+ i)))
      ((= i n) f2)
      ; empty body
      ))

(defun fib (n)
  "Compute the N'th Fibonacci number."
  (let ((f1 0)
	(f2 1)
	(i  0))
    (loop
     (if (= i n)
	 (return-from fib f2))
     ; empty body
     (psetf f1 f2
	    f2 (+ f1 f2)
	    i  (1+ i)))))
